package com.ldk.framework.service.impl;

import com.alipay.util.AlipayCore;
import com.ldk.base.framework.util.SystemUtil;
import com.ldk.framework.entity.*;
import com.ldk.framework.enums.FlowInOut;
import com.ldk.framework.enums.FlowPurpose;
import com.ldk.framework.enums.PayType;
import com.ldk.framework.enums.PlatformUserType;
import com.ldk.framework.enums.RechargeFrom;
import com.ldk.framework.enums.RechargeType;
import com.ldk.framework.enums.ServiceCode;
import com.ldk.framework.enums.TradePayStatus;
import com.ldk.framework.enums.TripCrewStatus;
import com.ldk.framework.enums.TripNoType;
import com.ldk.framework.enums.TripRefundStatus;
import com.ldk.framework.enums.TripStatus;
import com.ldk.framework.push.CustomMsgModule;
import com.ldk.framework.push.CustomMsgType;
import com.ldk.framework.push.PushCustomMsg;
import com.ldk.framework.push.PushTargetApp;
import com.ldk.framework.service.IBCServiceTripService;
import com.ldk.framework.service.ICJTServiceTripService;
import com.ldk.framework.service.ICjtSchedulService;
import com.weixin.api.WxMpService;
import com.weixin.api.WxMpServiceImpl;
import com.weixin.bean.RefundResData;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author xiangwl
 * 2017年3月10日
 * com.ldk.framework.service.impl
 * BCServiceTripService
 */
@Service
public class CJTServiceTripService extends ServiceTripService implements ICJTServiceTripService {

    @Autowired
    private ICjtSchedulService cjtSchedulService;

    @Override
    @Transactional
    public Boolean publish(final String dbKey, final ServiceTrip entity, ServiceTrip driverServiceTrip, Double price) throws Exception {
        if (entity == null)
            return false;
        if (driverServiceTrip == null)
            return false;
        Boolean success = false;
        int row = insert(dbKey, entity);
        if (row > 0) {


            //添加状态记录
            TripStatusRecord record = new TripStatusRecord();
            record.setOrderNo(entity.getTripNo());
            record.setStatusName(TripStatus.Publish.getName());
            record.setStatusValue(TripStatus.Publish.getValue());
            record.setTip(TripStatus.Publish.getTip());
            record.setTime(SystemUtil.getAllSeconds());

            row = tripStatusRecordService.insert(dbKey, record);

            //插入费用明细
            ServicePriceRecord pricerecord = new ServicePriceRecord();
            pricerecord.setPrice(entity.getPayFee());
            pricerecord.setTripNo(entity.getTripNo());
            pricerecord.setName("票价");
            pricerecord.setDes(price + "1元 x " + entity.getCrewCount() + "人");
            pricerecord.setUpdateTime(SystemUtil.getAllSeconds());
            servicePriceRecordService.insert(dbKey, pricerecord);

            //添加司机行程人数记录
            ServiceTripCrews crewsEntity = new ServiceTripCrews();
            crewsEntity.setDriverTripNo(driverServiceTrip.getTripNo());//司机与用户为同一个行程
            crewsEntity.setCrewTripNo(entity.getTripNo());
            crewsEntity.setDriverOpenId(entity.getDriverOpenId());
            crewsEntity.setCrewOpenId(entity.getOpenId());
            crewsEntity.setCrewStatus(TripCrewStatus.OffTheCar.getValue());
            Boolean payStatus = entity.getPayStatus() != null &&
                    (entity.getPayStatus() == TradePayStatus.TRADE_SUCCESS.getValue()
                            || entity.getPayStatus() == TradePayStatus.TRADE_FINISHED.getValue());
            crewsEntity.setPayStatus(payStatus);
            crewsEntity.setCanceled(false);
            row = serviceTripCrewsService.insert(dbKey, crewsEntity);
        }
        success = row > 0;
        return success;
    }

    @Override
    @Transactional
    public Boolean userCancel(final String dbKey, final ServiceTrip trip, User user, Integer cancelType) throws Exception {
        if (trip == null || StringUtils.isBlank(trip.getTripNo()))
            return false;
        CjtSchedul queryschedul = new CjtSchedul();
        queryschedul.setId(trip.getSchedulId());
        CjtSchedul cjtSchedul = cjtSchedulService.selectOne("", queryschedul);
        if (cjtSchedul == null) {
            return false;
        }

        final String tripNo = trip.getTripNo();
        final String openId = trip.getOpenId();
        ServiceTrip entity = new ServiceTrip();
        entity.setTripNo(tripNo);
        if (cancelType == 1) {
            entity.setStatus(TripStatus.UserCancel.getValue());
        } else if (cancelType == 2) {
            entity.setStatus(TripStatus.Expired.getValue());
        }
        entity.setCompleteTime(SystemUtil.getAllSeconds());

        int row = updateByKey(dbKey, entity);
        if (row > 0) {

            //同时添加司机行程状态记录
            TripStatusRecord statusRecord = new TripStatusRecord();
            statusRecord.setOrderNo(entity.getTripNo());
            if (cancelType == 1) {
                statusRecord.setStatusName(TripStatus.UserCancel.getName());
                statusRecord.setStatusValue(TripStatus.UserCancel.getValue());
                statusRecord.setTip(TripStatus.UserCancel.getTip());
            } else if (cancelType == 2) {
                statusRecord.setStatusName(TripStatus.Expired.getName());
                statusRecord.setStatusValue(TripStatus.Expired.getValue());
                statusRecord.setTip(TripStatus.Expired.getTip());
            }
            statusRecord.setTime(SystemUtil.getAllSeconds());
            row = tripStatusRecordService.insert(dbKey, statusRecord);

            //如果司机已经接单了，则要修改司机行程里面的乘客行程状态为取消
            if (!StringUtils.isBlank(trip.getDriverOpenId())) {
                ServiceTripCrews tripCrews = new ServiceTripCrews();
                if (trip.getUserType() == PlatformUserType.CLIENT_USER.getValue()) {
                    tripCrews.setCrewTripNo(tripNo);
                    tripCrews.setCrewOpenId(trip.getOpenId());
                    serviceTripCrewsService.delete(dbKey, tripCrews);
                } else if (trip.getUserType() == PlatformUserType.DRIVER_USER.getValue()) {
                    tripCrews.setDriverTripNo(tripNo);
                    tripCrews.setDriverOpenId(trip.getOpenId());
                    serviceTripCrewsService.delete(dbKey, tripCrews);
                }
            }
            //如未支付，则直接取消订单
            if (trip.getStatus() == TripStatus.WaitingPay.getValue()) {
                return true;
            }

            //如果已支付，需要改变司机行程乘客数量
            if (trip.getStatus() == TripStatus.Payed.getValue()) {
                ServiceTrip querydriver = new ServiceTrip();
                querydriver.setDriverOpenId(trip.getDriverOpenId());
                querydriver.setUserType(PlatformUserType.DRIVER_USER.getValue());
                ServiceTrip driverserviceTrip = selectOne(dbKey, querydriver);
                if (driverserviceTrip != null) {
                    ServiceTrip serviceTrip = new ServiceTrip();
                    serviceTrip.setTripNo(driverserviceTrip.getTripNo());
                    serviceTrip.setCrewCount(driverserviceTrip.getCrewCount() - trip.getCrewCount());
                    updateByKey(dbKey, serviceTrip);
                    //排班记录中修改人数
                    if (cjtSchedul != null) {
                        CjtSchedul cjtSchedul1 = new CjtSchedul();
                        cjtSchedul1.setId(cjtSchedul.getId());
                        cjtSchedul1.setHaveSeat(cjtSchedul.getHaveSeat() + trip.getCrewCount());
                        cjtSchedulService.updateByKey(dbKey, cjtSchedul1);
                    }
                }
            }

            //取消规则。
            //12小时前，全额退款
            //2-12小时， 按票面金额20%计收退费手续费
            //发车前2小时内，  按票面金额80%计收退费手续费
            //发车后，不进行退款
            //计算退款金额
            long durntime = trip.getGoTime() - SystemUtil.getAllSeconds();
            double refundPrice = 0.0;
            if (durntime >= 12 * 60 * 60) {
                refundPrice = trip.getPayFee();
            } else if (durntime >= 2 * 60 * 60) {
                refundPrice = trip.getPayFee() * 0.8;
            } else if (durntime >= 0) {
                refundPrice = trip.getPayFee() * 0.2;
            } else {
                refundPrice = 0.0;
            }

            User userEntity = new User();
            userEntity.setUserId(user.getUserId());


            //如果支付成功，且状态为支付完成的状态，需要执行退款功能。
            if (refundPrice > 0 && trip.getPayFee() != null && trip.getPayStatus() != null && trip.getPayStatus() == TradePayStatus.TRADE_SUCCESS.getValue()) {

                //判断任务支付方式执行退款功能
                Boolean refundSucceed = false;
                int refundStatus = TripRefundStatus.FAILED.getValue();

                //余额支付
                if (trip.getPayId() == PayType.Balance.getId()) {
                    if (user != null) {
                        double beforeBalance = user.getBalance();
                        double afterBalance = user.getBalance() + refundPrice;
                        userEntity = new User();
                        userEntity.setUserId(user.getUserId());
                        userEntity.setBalance(afterBalance);
                        int row1 = userService.updateByKey(dbKey, userEntity);
                        refundSucceed = row1 > 0;
                        if (refundSucceed) {
                            //添加用户充值记录
                            RechargeRecord record = new RechargeRecord();
                            record.setRecordNo(SystemUtil.generateRandomNo(""));
                            record.setPhoneNo(user.getOpenId());
                            record.setUserType(PlatformUserType.CLIENT_USER.getValue());
                            record.setRechargeMoney(trip.getPayFee());
                            record.setRechargeFrom(RechargeFrom.FROM_SYSTEM.getValue());
                            record.setBeforeBalance(beforeBalance);
                            record.setAfterBalance(afterBalance);
                            record.setRechargeTime(SystemUtil.getAllSeconds());
                            record.setRechargeType(RechargeType.UserCancelTrip.getValue());
                            record.setOperator("system");
                            record.setRemark("用户取消城际通行程退款");
                            record.setLinkTaskNo(tripNo);
                            rechargeRecordService.insert(dbKey, record);
                        }
                        refundStatus = refundSucceed ? TripRefundStatus.SUCCEESS.getValue() : TripRefundStatus.FAILED.getValue();
                    }
                }//微信支付
                else if (trip.getPayId() == PayType.Tenpay.getId()) {
                    //获取腾讯支付记录
                    String payTradeNo = trip.getPayTradeNo();
                    Tenpay query = new Tenpay();
                    query.setTransactionId(payTradeNo);

                    Tenpay tenpay = tenpayService.selectOne(dbKey, query);
                    if (tenpay != null) {
                        WxMpService wxMpService = new WxMpServiceImpl();
                        Double totalFee = trip.getPayFee() * 100;
                        Double refundfee = refundPrice * 100;
                        int fee = totalFee.intValue();
                        int refee = refundfee.intValue();
                        RefundResData refundResData = wxMpService.refund(tenpay.getOutTradeNo(), tenpay.getTransactionId(), "", "", fee, refee, tenpay.getFeeType());

                        refundSucceed = refundResData.isResultSuccess();
                    }
                    refundStatus = refundSucceed ? TripRefundStatus.SUCCEESS.getValue() : TripRefundStatus.FAILED.getValue();
                }//支付宝支付
                else if (trip.getPayId() == PayType.Alipay.getId()) {
                    //新的支付宝退款流程：直接调接口退款
                    String payTradeNo = trip.getPayTradeNo();
                    Alipay query = new Alipay();
                    query.setTradeNo(payTradeNo);

                    Alipay alipay = alipayService.selectOne(dbKey, query);
                    if (alipay != null) {
                        refundSucceed = AlipayCore.refund(alipay.getOutTradeNo(), alipay.getTradeNo(), (float) refundPrice, "user cancel order refund", "", "", "", "");
                        refundStatus = refundSucceed ? TripRefundStatus.SUCCEESS.getValue() : TripRefundStatus.FAILED.getValue();
                        if (refundSucceed) {
                            Alipay refundAlipay = new Alipay();
                            refundAlipay.setPayId(alipay.getPayId());
                            refundAlipay.setRefundFee(alipay.getTotalFee());
                            refundAlipay.setTradeStatus("TRADE_CLOSED");

                            alipayService.updateByKey(dbKey, refundAlipay);
                        }
                    }
                    logger.error("userCancelTask.alipay::refundSucceed" + refundSucceed + ",refundStatus=" + refundStatus);
                }
                TripRefundRecord refundRecord = new TripRefundRecord();
                refundRecord.setTaskNo(tripNo);
                refundRecord.setRefundFee(trip.getPayFee());
                refundRecord.setTaskPayId(trip.getPayId());
                refundRecord.setTaskPayTradeNo(trip.getPayTradeNo());
                refundRecord.setRefundStatus(refundStatus);
                refundRecord.setRefundTime(SystemUtil.getAllSeconds());
                //设置备注为平台资金流动用途
                refundRecord.setRemark(FlowPurpose.USER_CANCEL_TRIP_REFUND.getName());
                //添加任务退款记录
                tripRefundRecordService.insert(dbKey, refundRecord);

                //退款成功后添加平台资金流动记录,支付宝的再后台处理后在添加这个记录
                if (refundSucceed) {
                    //司机、平台、分公司收入
                    double refundincome = trip.getPayFee() - refundPrice;
                    if (refundincome > 0) {
                        //后面在做进一步的处理
                    }
                    PlatformFundFlowRecord flowRecord = new PlatformFundFlowRecord();
                    flowRecord.setRecordNo(SystemUtil.generateRandomNo(""));
                    flowRecord.setUserUniqueId(trip.getOpenId());
                    flowRecord.setUserType(PlatformUserType.CLIENT_USER.getValue());
                    flowRecord.setFlowAmount(trip.getPayFee());
                    flowRecord.setInOut(FlowInOut.OUT.getValue());
                    flowRecord.setFlowFrom("平台" + trip.getPayName());
                    flowRecord.setFlowTo("用户" + trip.getPayName());
                    flowRecord.setFlowMode(trip.getPayId());
                    flowRecord.setLinkNo(tripNo);
                    flowRecord.setPurpose(FlowPurpose.USER_CANCEL_TRIP_REFUND.getName());
                    flowRecord.setRemark("用户支付行程费用退还给用户");

                    platformFundFlowRecordService.insert(dbKey, flowRecord);
                }
            }
        }
        //取消成功，则推送
        if (row > 0) {
            //推送给用户取消行程成功
            new Thread(new Runnable() {

                @Override
                public void run() {
                    List<String> aliasList = new ArrayList<String>();
                    aliasList.add(openId);
                    String toUser = openId;
                    String message = String.format("用户取消%s行程", CustomMsgModule.BC.getName());
                    String content = String.format("你已成功取消[%s]行程", CustomMsgModule.BC.getName());
                    PushCustomMsg customMsg = new PushCustomMsg();
                    customMsg.setModule(CustomMsgModule.BC.getValue());
                    customMsg.setType(CustomMsgType.UserCancelTrip.getValue());
                    customMsg.setKey(tripNo);

                    PushMessage pushMessage = new PushMessage();
                    pushMessage.setContent(content);
                    pushMessage.setModule(CustomMsgModule.BC.getValue());
                    pushMessage.setTitle(message);
                    pushMessage.setTripNo(tripNo);
                    pushMessage.setToUser(toUser);
                    pushMessage.setMessage(message);
                    pushMessage.setContent(content);
                    pushMessage.setExtras(customMsg.toJson());
                    pushMessage.setPushTime(SystemUtil.getAllSeconds());
                    pushMessage.setJumpUrl("");

                    pushMessageService.pushToUser(dbKey, pushMessage, PushTargetApp.Client, customMsg, aliasList, true);
                }
            }).start();
            //司机接单或用户已经上车的状态都要推送给司机消息
            if (trip.getStatus() >= TripStatus.Accept.getValue() &&
                    trip.getStatus() < TripStatus.Complete.getValue()) {
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        List<String> aliasList = new ArrayList<String>();
                        aliasList.add(trip.getDriverOpenId());
                        String toUser = trip.getDriverOpenId();
                        String message = String.format("用户取消%s行程", CustomMsgModule.BC.getName());
                        String content = String.format("用户已成功取消[%s]行程,行程单号为：%s", CustomMsgModule.BC.getName(), tripNo);
                        PushCustomMsg customMsg = new PushCustomMsg();
                        customMsg.setModule(CustomMsgModule.BC.getValue());
                        customMsg.setType(CustomMsgType.UserCancelTrip.getValue());
                        customMsg.setKey(tripNo);

                        PushMessage pushMessage = new PushMessage();
                        pushMessage.setContent(content);
                        pushMessage.setModule(CustomMsgModule.BC.getValue());
                        pushMessage.setTitle(message);
                        pushMessage.setTripNo(tripNo);
                        pushMessage.setToUser(toUser);
                        pushMessage.setMessage(message);
                        pushMessage.setContent(content);
                        pushMessage.setExtras(customMsg.toJson());
                        pushMessage.setPushTime(SystemUtil.getAllSeconds());
                        pushMessage.setJumpUrl("");

                        pushMessageService.pushToUser(dbKey, pushMessage, PushTargetApp.Driver, customMsg, aliasList, true);
                    }
                }).start();
            }

        }

        return row > 0;
    }


    @Override
    @Transactional
    public synchronized Boolean driverAccept(final String dbKey, final ServiceTrip userTrip) throws Exception {
        if (userTrip == null)
            return false;

        ServiceTrip userTripEntity = new ServiceTrip();
        //此参数在外部设置，这里取出来修改
        userTripEntity.setDriverOpenId(userTrip.getDriverOpenId());
        userTripEntity.setTripNo(userTrip.getTripNo());
        userTripEntity.setStatus(TripStatus.Accept.getValue());

        int row = updateByKey(dbKey, userTripEntity);
        if (row > 0) {
            //添加行程状态
            TripStatusRecord statusRecord = new TripStatusRecord();
            statusRecord.setOrderNo(userTrip.getTripNo());
            statusRecord.setStatusName(TripStatus.Accept.getName());
            statusRecord.setStatusValue(TripStatus.Accept.getValue());
            statusRecord.setTip(TripStatus.Accept.getTip());
            statusRecord.setTime(SystemUtil.getAllSeconds());

            row = tripStatusRecordService.insert(dbKey, statusRecord);

            //删除此行程的可接单记录
            DriverReceiveTrip receiveTrip = new DriverReceiveTrip();
            receiveTrip.setTripNo(userTrip.getTripNo());
            driverReceiveTripService.delete(dbKey, receiveTrip);
        }
        if (row > 0) {
            //系统创建司机行程，与用户的行程一样，为了与专线和顺风车业务统一
            String driverTripNo = SystemUtil.generateOrderNo(TripNoType.TRIP.getPrefix());
            ServiceTrip driverTrip = new ServiceTrip();
            driverTrip.setTripNo(driverTripNo);
            driverTrip.setServiceCode(userTrip.getServiceCode());
            driverTrip.setUserType(PlatformUserType.DRIVER_USER.getValue());
            driverTrip.setOpenId(userTrip.getDriverOpenId());
            driverTrip.setRoadId(userTrip.getRoadId());
            driverTrip.setStartLocation(userTrip.getStartLocation());
            driverTrip.setStartLon(userTrip.getStartLon());
            driverTrip.setStartLat(userTrip.getStartLat());
            driverTrip.setEndLocation(userTrip.getEndLocation());
            driverTrip.setEndLon(userTrip.getEndLon());
            driverTrip.setEndLat(userTrip.getEndLat());
            driverTrip.setCreateTime(userTrip.getCreateTime());
            driverTrip.setCarRank(userTrip.getCarRank());
            driverTrip.setCarSeats(userTrip.getCarSeats());
            driverTrip.setGoTime(userTrip.getGoTime());
            //一对一满员了
            driverTrip.setStatus(TripStatus.Accept.getValue());
            driverTrip.setCrewCount(1);
            driverTrip.setDistance(userTrip.getDistance());
            driverTrip.setDuration(userTrip.getDuration());
            driverTrip.setBillingMode(userTrip.getBillingMode());
            //费用
            driverTrip.setPayFee(userTrip.getPayFee());
            driverTrip.setDepositPayFee(userTrip.getDepositPayFee());
            //其他默认值
            driverTrip.setHasAsign(false);
            driverTrip.setHasComment(false);
            driverTrip.setHasComplaint(false);
            //添加司机行程
            insert(dbKey, driverTrip);
            //添加行程状态
            TripStatusRecord statusRecord = new TripStatusRecord();
            statusRecord.setOrderNo(userTrip.getTripNo());
            statusRecord.setStatusName(TripStatus.Accept.getName());
            statusRecord.setStatusValue(TripStatus.Accept.getValue());
            statusRecord.setTip(TripStatus.Accept.getTip());
            statusRecord.setTime(SystemUtil.getAllSeconds());
            row = tripStatusRecordService.insert(dbKey, statusRecord);

            //添加司机行程人数记录
            ServiceTripCrews crewsEntity = new ServiceTripCrews();
            crewsEntity.setDriverTripNo(driverTripNo);//司机与用户为同一个行程
            crewsEntity.setCrewTripNo(userTrip.getTripNo());
            crewsEntity.setDriverOpenId(userTrip.getDriverOpenId());
            crewsEntity.setCrewOpenId(userTrip.getOpenId());
            crewsEntity.setCrewStatus(TripCrewStatus.OffTheCar.getValue());
            Boolean payStatus = userTrip.getPayStatus() != null &&
                    (userTrip.getPayStatus() == TradePayStatus.TRADE_SUCCESS.getValue()
                            || userTrip.getPayStatus() == TradePayStatus.TRADE_FINISHED.getValue());
            crewsEntity.setPayStatus(payStatus);
            crewsEntity.setCanceled(false);

            row = serviceTripCrewsService.insert(dbKey, crewsEntity);
        }
        //推送给用户告知司机已接单
        if (row > 0) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    //用户行程单号
                    String tripNo = userTrip.getTripNo();
                    List<String> aliasList = new ArrayList<String>();
                    aliasList.add(userTrip.getOpenId());
                    String toUser = userTrip.getOpenId();
                    String message = String.format("司机接受%s行程", CustomMsgModule.BC.getName());
                    String content = String.format("司机已成功接受[%s]行程,行程单号为：%s", CustomMsgModule.BC.getName(), tripNo);
                    PushCustomMsg customMsg = new PushCustomMsg();
                    customMsg.setModule(CustomMsgModule.BC.getValue());
                    customMsg.setType(CustomMsgType.DriverAcceptTrip.getValue());
                    customMsg.setKey(tripNo);

                    PushMessage pushMessage = new PushMessage();
                    pushMessage.setContent(content);
                    pushMessage.setModule(CustomMsgModule.BC.getValue());
                    pushMessage.setTitle(message);
                    pushMessage.setTripNo(tripNo);
                    pushMessage.setToUser(toUser);
                    pushMessage.setMessage(message);
                    pushMessage.setContent(content);
                    pushMessage.setExtras(customMsg.toJson());
                    pushMessage.setPushTime(SystemUtil.getAllSeconds());
                    pushMessage.setJumpUrl("");

                    pushMessageService.pushToUser(dbKey, pushMessage, PushTargetApp.Client, customMsg, aliasList, true);
                }
            }).start();
        }

        return row > 0;
    }
}
